package com.pz.gulimall.ware.config;

import com.pz.gulimall.common.exception.BizCodeEnum;
import com.pz.gulimall.common.exception.RRException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
@Slf4j
@RefreshScope
public class MQConfig implements ApplicationContextAware {
    /**
     *生产者可靠性配置
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);

        //设置发送消息确认的回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            log.info("correlationData-{}, ack-{}， cause-{}", correlationData, ack, cause);
        });

        //设置消息抵达队列的确认回调（消息没有抵达指定队列的时候回调）
        rabbitTemplate.setReturnsCallback(returned ->
                {
                    log.error("消息发送失败 >>> 应答码-{}, 原因-{}, 交换机-{}, 路由-{}, 消息-{}",
                            returned.getReplyCode(), returned.getReplyText(), returned.getExchange(), returned.getRoutingKey(), returned.getMessage());
                    throw new RRException(BizCodeEnum.ORDER_MESSAGE_SENDEXCEPTION.getMsg()+returned.getReplyText(), BizCodeEnum.ORDER_MESSAGE_SENDEXCEPTION.getCode());
                }
        );
    }

    /**------------------------------------  延时队列配置 ------------------------------------------------**/
    public static final String wareReleaseQueName = "stock.release.que";
    public static final String wareEventExchangeName = "wareEvent.exchange";
    public static final String deadLetterRoutingKey = "stock,locked";
    public static final String wareReleaseRoutingKey = "stock.release";
    private static final String wareDelayQueName = "stock.delay.que";

    @Value("${delayTime}")
    public Long delayTime; //延迟队列的延迟时间 ms

    /**
     * 死信交换机
     */
    @Bean
    public Exchange orderEventExchange(){
        return new TopicExchange(wareEventExchangeName, true, false);
    }

    /**
     * 死信延迟队列
     */
    @Bean
    public Queue orderDelayQue(){
        Map<String, Object> arguments = new HashMap<>();
        //设置消息属性
        arguments.put("x-dead-letter-exchange", wareEventExchangeName);
        arguments.put("x-dead-letter-routing-key", wareReleaseRoutingKey);
        arguments.put("x-message-ttl", delayTime);
        return new Queue(wareDelayQueName, true, false, false, arguments);
    }

    /**
     * 提供给外界访问的队列，接收死信消息
     */
    @Bean
    public Queue orderReleaseQue(){
        return new Queue(wareReleaseQueName, true, false, false);
    }

    /**
     * 死信队列绑定
     */
    @Bean
    public Binding orderReleaseOrderBinding() {
        return new Binding(wareReleaseQueName, Binding.DestinationType.QUEUE, wareEventExchangeName, wareReleaseRoutingKey,null);
    }

    /**
     * 延迟队列绑定
     */
    @Bean
    public Binding orderDelayOrderBinding() {
        return new Binding(wareDelayQueName, Binding.DestinationType.QUEUE, wareEventExchangeName, deadLetterRoutingKey, null);
    }

    /**------------------------------------  延时队列配置 ------------------------------------------------**/
}
